package controls {
	import controls.demographic.DemographicControl;
	import controls.instructions.InstructionsControl;
	import controls.questions.MultipleChoiceQuestion;
	import controls.questions.QuestionLoader;
	
	import data.DemographicResult;
	import data.ExperimentResults;
	import data.Result;
	
	import events.ExperimentEvent;
	
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.net.URLVariables;
	import flash.utils.Timer;
	
	import mx.containers.Panel;
	import mx.events.FlexEvent;
	
	
	/**
	 * @author Brent Kersanske
	 */ 
	public class ExperimentManagerClass extends Panel {
		
		private static const RESULTS_SUBMIT_URL:String = "results.php";
		
		[Bindable]
		public var instructionsControl:InstructionsControl;
		
		[Bindable]
		public var experimentResults:ExperimentResults;
		
		[Bindable]
		public var currentQuestion:MultipleChoiceQuestion;
		
		private var questionLoader:QuestionLoader;		
				
		private var demographicControl:DemographicControl;
		
		private var loadingControl:LoadingControl;
				
		public function ExperimentManagerClass() {
			addEventListener(FlexEvent.CREATION_COMPLETE, handleCreationComplete);	
		}
		
		private function handleCreationComplete(e:FlexEvent):void {
			init();	
		}
		
		private function init():void {
			this.instructionsControl.addEventListener(ExperimentEvent.INSTRUCTIONS_COMPLETE, handleInstructionsComplete);
		}
		
		/**
		 * When the user signals with an event that he has completed reading the instructions, initialize the demographic control.
		 */ 
		private function handleInstructionsComplete(e:ExperimentEvent):void {
			this.removeAllChildren();
			initializeDemographicControl();
		}
		
		/**
		 * Initialize the demographic control!
		 */ 
		private function initializeDemographicControl():void {
			this.demographicControl = new DemographicControl();
			this.demographicControl.addEventListener(ExperimentEvent.START_EXPERIMENT, handleDemographicComplete);
			this.addChild(this.demographicControl);			
		}		
				
		/**
		 * When the user has completed the demographic section, load the questions for the experiment.
		 */ 
		private function handleDemographicComplete(e:ExperimentEvent):void {
			var demoResult:DemographicResult = (e.a as DemographicResult);
			this.experimentResults.addDemographicResult(demoResult);
			this.removeAllChildren();
			initializeQuestionLoader();
		}
		
		private function initializeQuestionLoader():void {
			this.questionLoader = new QuestionLoader();
			this.questionLoader.loadRandomQuestionSet();
			this.questionLoader.addEventListener(ExperimentEvent.QUESTION_LOADING_COMPLETE, handleQuestionLoadingComplete);
		}
		
		/**
		 * Wait until all questions have been loaded via HTTP before adding one to the stage.
		 */ 
		private function handleQuestionLoadingComplete(e:ExperimentEvent):void {
			loadNextQuestion();
		}
		
		/**
		 * Load a random question set for the experiment!
		 */ 
		private function loadNextQuestion():void {
			this.removeAllChildren();
			this.currentQuestion = this.questionLoader.getNextQuestion();
			this.currentQuestion.addEventListener(ExperimentEvent.NEW_RESULT, handleNewResult);
			this.addChild(this.currentQuestion);
		}
		
		private function handleNewResult(e:ExperimentEvent):void {
			var questionResult:Result = (e.a as Result);
			this.experimentResults.addQuestionResult(questionResult);
			this.currentQuestion.clearAll();
			if(this.questionLoader.moreQuestionsAvailable()) {
				loadNextQuestion();
			} else {
				submitResults();
			}
		}
		
		private function submitResults():void {
			initializeLoadingControl();
			var resultsRequest:URLRequest = new URLRequest(RESULTS_SUBMIT_URL);
			var resultsData:URLVariables  = new URLVariables();
			var resultsLoader:URLLoader   = new URLLoader();
			resultsData.expData 		  = this.experimentResults.getResultsAsHTMLTable();
			resultsRequest.method 		  = URLRequestMethod.GET;
			resultsRequest.data			  = resultsData;
			configureListeners(resultsLoader);
			resultsLoader.load(resultsRequest);
		}		
				
		private function initializeLoadingControl():void {
			this.removeAllChildren();
			this.loadingControl = new LoadingControl();
			this.loadingControl.loadingLabelText = "Submitting results. Please wait...";
			this.addChild(this.loadingControl);			
		}
		
		private function configureListeners(dispatcher:IEventDispatcher):void {
            dispatcher.addEventListener(Event.COMPLETE, completeHandler);
            dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
            dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
        }

        private function completeHandler(event:Event):void {
        	this.loadingControl.signalCompletion("Results submitted. Thank you for your time.");
        }


        private function securityErrorHandler(event:SecurityErrorEvent):void {
           this.loadingControl.signalFailure("Security error :(");
        }

        private function ioErrorHandler(event:IOErrorEvent):void {
        	this.loadingControl.signalFailure("IO Error :(");  
        }
	}
}